/* SPDX-License-Identifier: GPL-2.0 */
/*  Himax Android Driver Sample Code for common functions
 *
 *  Copyright (C) 2021 Himax Corporation.
 *
 *  This software is licensed under the terms of the GNU General Public
 *  License version 2,  as published by the Free Software Foundation,  and
 *  may be copied,  distributed,  and modified under those terms.
 *
 *  This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 */

#ifndef HIMAX_COMMON_H
#define HIMAX_COMMON_H
#include<linux/time.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/async.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/input/mt.h>
#include <linux/firmware.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/pm_wakeup.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <linux/kallsyms.h>
#include <linux/of_gpio.h>
#include <linux/version.h>
#include "himax_platform.h"

#define HIMAX_DRIVER_VER "Sample_code_A09.13.1"

#define FLASH_DUMP_FILE "/sdcard/HX_Flash_Dump.bin"

/*===========Himax Option function=============*/
#define HX_BOOT_UPGRADE					(0x00)
#define HX_EXCP_RECOVERY				(0x00)
#define HX_PROTOCOL_A					(0x00)
#define HX_PROTOCOL_B_3PA				(0x01)
#define HX_RST_PIN_FUNC					(0x01)
#define HX_TP_INSPECT_MODE				(0x01)
#define HX_FIX_TOUCH_INFO				(0x00)
#define FCA_PROTOCOL_EN					(0x00)
#define HX_WPBP_ENABLE					(0x01)
#define HX_SMART_WAKEUP					(0x00)
#define HX_GESTURE_TRACK				(0x00)
/*=============================================*/
/* Enable it if driver go into suspend/resume twice */
/*#define HX_CONFIG_FB				(0x00)*/
/* Enable it if driver go into suspend/resume twice */
/*#define HX_CONFIG_DRM				(0x00)*/

#if defined(HX_CONFIG_FB)
#include <linux/notifier.h>
#include <linux/fb.h>
#elif defined(HX_CONFIG_DRM)
/*#include <linux/msm_drm_notify.h>*/
#endif

#if (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE)
#define KERNEL_VER_ABOVE_4_14
#endif

/* WP GPIO setting, decided by which pin direct to OS side, WP need pin */
/* high either GPIO0 or GPIO4 */
/* #define WP_GPIO0 */
#define WP_GPIO4				(0x01)

#if (HX_BOOT_UPGRADE == 0x01)
/* FW Auto upgrade case, you need to setup the fix_touch_info of module
 */
#define BOOT_UPGRADE_FWNAME "Himax_firmware.bin"
#endif


#if defined(HX_CONTAINER_SPEED_UP)
/*Resume queue delay work time after LCM RST (unit:ms)
 */
#define DELAY_TIME 40
#endif

#if defined(HX_CONFIG_FB)
int fb_notifier_callback(struct notifier_block *self,
		unsigned long event, void *data);
#elif defined(HX_CONFIG_DRM)
int drm_notifier_callback(struct notifier_block *self,
			unsigned long event, void *data);
#endif

#define HX_MAX_WRITE_SZ    (64 * 1024 + 4)

#define HX_83191A_SERIES_PWON		"HX83191A"
#define HX_83192A_SERIES_PWON		"HX83192A"
#define HX_83193A_SERIES_PWON		"HX83193A"

#define HX_TP_BIN_CHECKSUM_SW		1
#define HX_TP_BIN_CHECKSUM_HW		2
#define HX_TP_BIN_CHECKSUM_CRC		3

#define SHIFTBITS			5

#define FW_SIZE_128k		131072
#define FW_SIZE_FULL		176128

#define NO_ERR					0
#define I2C_FAIL				-1
#define HX_INIT_FAIL			-1
#define MEM_ALLOC_FAIL			-2
#define INPUT_REGISTER_FAIL		-3
#define FW_NOT_READY			4
#define LENGTH_FAIL				-5
#define OPEN_FILE_FAIL			-6
#define PROBE_FAIL				-7
#define ERR_WORK_OUT			-8
#define ERR_TEST_FAIL			-9
#define HW_CRC_FAIL				1

#define HX_FINGER_ON			1
#define HX_FINGER_LEAVE			2

#if defined(__EMBEDDED_FW__)
extern const uint8_t _binary___Himax_firmware_bin_start[];
extern const uint8_t _binary___Himax_firmware_bin_end[];
extern struct firmware g_embedded_fw;
#endif

enum HX_TS_PATH {
	HX_REPORT_COORD = 1,
	HX_REPORT_SMWP_EVENT,
	HX_REPORT_COORD_RAWDATA,
};

enum HX_TS_STATUS {
	HX_TS_GET_DATA_FAIL = -4,
	HX_EXCP_EVENT,
	HX_CHKSUM_FAIL,
	HX_PATH_FAIL,
	HX_TS_NORMAL_END = 0,
	HX_EXCP_REC_OK,
	HX_READY_SERVE,
	HX_REPORT_DATA,
	HX_EXCP_WARNING,
	HX_IC_RUNNING,
	HX_ZERO_EVENT_COUNT,
	HX_RST_OK,
};

enum cell_type {
	CHIP_IS_ON_CELL,
	CHIP_IS_IN_CELL
};
#if (HX_SMART_WAKEUP == 0x01)
#define HX_KEY_DOUBLE_CLICK                KEY_POWER
#define HX_KEY_SINGLE_CLICK                KEY_POWER
#endif

#if (HX_FIX_TOUCH_INFO == 0x01)
enum fix_touch_info {
	FIX_HX_RX_NUM = 0,
	FIX_HX_TX_NUM = 0,
	FIX_HX_MAX_PT = 0,
	FIX_HX_INT_IS_EDGE = false,
	FIX_HX_IS_ID_EN = false,
	FIX_HX_ID_PALM_EN = false,
};
#endif

struct himax_ic_data {
	int vendor_arch_ver;
	int vendor_config_ver;
	int vendor_touch_cfg_ver;
	int vendor_display_cfg_ver;
	int vendor_cid_maj_ver;
	int vendor_cid_min_ver;
	int vendor_panel_ver;
	int vendor_sensor_id;
	int ic_adc_num;
	uint8_t vendor_config_date[12];
	uint8_t vendor_cus_info[12];
	uint8_t vendor_proj_info[12];
	uint8_t vendor_ic_id[13];
	int HX_RX_NUM;
	int HX_TX_NUM;
	int HX_X_RES;
	int HX_Y_RES;
	int HX_MAX_PT;
	bool HX_X_REVERSE;
	bool HX_Y_REVERSE;
	bool HX_INT_IS_EDGE;
	bool HX_IS_ID_EN;
	bool HX_ID_PALM_EN;
	bool DA_PROTOCOL_EN;
};

struct himax_target_report_data {
	int *x;
	int *y;
	int *w;
	int *finger_id;
	int finger_on;
	int finger_num;
	int *fpt_cnt;
#if (HX_SMART_WAKEUP == 0x01)
	int SMWP_event_chk;
#endif
};

struct himax_report_data {
	int touch_all_size;
	int raw_cnt_max;
	int raw_cnt_rmd;
	int touch_info_size;
	uint8_t	finger_num;
	uint8_t	finger_on;
	uint8_t *hx_coord_buf;
	uint8_t hx_state_info[2];
#if (HX_SMART_WAKEUP == 0x01)
	int event_size;
	uint8_t *hx_event_buf;
#endif
	int rawdata_size;
	uint8_t diag_cmd;
	uint8_t *hx_rawdata_buf;
	uint8_t rawdata_frame_size;
};

struct himax_ts_data {
	bool initialized;
	bool suspended;
	atomic_t suspend_mode;
	uint8_t x_channel;
	uint8_t y_channel;
	uint8_t useScreenRes;
	uint8_t diag_cmd;
	char chip_name[30];
	uint8_t protocol_type;
	uint8_t first_pressed;
	uint8_t coord_data_size;
	uint8_t area_data_size;
	uint8_t coordInfoSize;
	uint8_t raw_data_frame_size;
	uint8_t nFinger_support;
	uint8_t irq_enabled;
	uint8_t diag_self[50];
	uint16_t finger_pressed;
	uint16_t last_slot;
	uint16_t pre_finger_mask;
	uint16_t old_finger;
	int hx_point_num;

	uint32_t debug_log_level;
	uint32_t widthFactor;
	uint32_t heightFactor;

	int lcm_gpio;
	int rst_gpio;
	int use_irq;
	int (*power)(int on);
	int pre_finger_data[10][2];

	struct device *dev;
	struct workqueue_struct *himax_wq;
	struct work_struct work;
	struct input_dev *input_dev;

	struct hrtimer timer;
	struct i2c_client *client;
	struct himax_i2c_platform_data *pdata;
	struct mutex rw_lock;
	atomic_t irq_state;
	spinlock_t irq_lock;

/******* SPI-start *******/
	struct spi_device	*spi;
	int hx_irq;
	uint8_t *xfer_buff;
/******* SPI-end *******/

	int in_self_test;
	int suspend_resume_done;
	int bus_speed;

#if defined(HX_CONFIG_FB) || defined(HX_CONFIG_DRM)
	struct notifier_block fb_notif;
	struct workqueue_struct *himax_att_wq;
	struct delayed_work work_att;
#endif

	struct workqueue_struct *flash_wq;
	struct work_struct flash_work;

#if (HX_BOOT_UPGRADE == 0x01)
	struct workqueue_struct *himax_boot_upgrade_wq;
	struct delayed_work work_boot_upgrade;
#endif

#if defined(HX_CONTAINER_SPEED_UP)
	struct workqueue_struct *ts_int_workqueue;
	struct delayed_work ts_int_work;
#endif

	struct workqueue_struct *himax_diag_wq;
	struct delayed_work himax_diag_delay_wrok;
#if (HX_SMART_WAKEUP == 0x01)
	uint8_t SMWP_enable;
	uint8_t gesture_cust_en[26];
	struct wakeup_source ts_SMWP_wake_lock;
#endif
	uint8_t GTS_range;
};

struct himax_debug {
	void (*fp_ts_dbg_func)(struct himax_ts_data *ts, int start);
	int (*fp_set_diag_cmd)(struct himax_ic_data *ic_data,
				struct himax_report_data *hx_touch_data);
};

enum input_protocol_type {
	PROTOCOL_TYPE_A	= 0x00,
	PROTOCOL_TYPE_B	= 0x01,
};
#if (HX_SMART_WAKEUP == 0x01)
void himax_set_SMWP_func(uint8_t SMWP_enable);

#define GEST_PTLG_ID_LEN    (4)
#define GEST_PTLG_HDR_LEN    (4)
#define GEST_PTLG_HDR_ID1    (0xCC)
#define GEST_PTLG_HDR_ID2    (0x44)
#define GEST_PT_MAX_NUM        (128)

extern uint8_t *wake_event_buffer;
#endif
extern int g_mmi_refcnt;
extern int *g_inspt_crtra_flag;
extern uint32_t g_hx_chip_inited;
extern uint8_t g_flash_progress;
/*void himax_HW_reset(uint8_t loadconfig,uint8_t int_off);*/

int himax_chip_common_suspend(struct himax_ts_data *ts);
int himax_chip_common_resume(struct himax_ts_data *ts);

struct himax_core_fp;
extern struct himax_core_fp g_core_fp;
extern struct himax_ts_data *private_ts;
extern struct himax_ic_data *ic_data;
extern struct device *g_device;

#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
	int himax_debug_init(void);
	int himax_debug_remove(void);
#endif

#if defined(CONFIG_TOUCHSCREEN_HIMAX_SELF_TEST)
	extern char *g_rslt_data;
#endif

int himax_parse_dt(struct himax_ts_data *ts,
			struct himax_i2c_platform_data *pdata);
int himax_report_data(struct himax_ts_data *ts, int ts_path, int ts_status);

int himax_report_data_init(void);

int himax_dev_set(struct himax_ts_data *ts);
int himax_input_register_device(struct input_dev *input_dev);
int himax_chip_self_test(struct seq_file *s, void *v);
void himax_report_all_leave_event(struct himax_ts_data *ts);
void himax_mcu_clear_event_stack(void);
#endif
extern struct timespec64 time_diff(struct timespec64 start, struct timespec64 end);
